package com.merge.sample;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.merge.sample.model.MData;
import com.merge.sample.model.RData;
import com.merge.sample.util.MyUtil;
import com.merge.sample.util.XMLPaser;

public class DefaultXMLFileMerge implements CanMerge {
	public static final String ln = System.getProperty("line.separator");
	private String beginComment, endComment;
	private Pattern filePattern = Pattern.compile("<.*?name=\"([^\"]+)[^>]*>");
	private String projectName = "";
	List<RData> srdl = null;
	
	public DefaultXMLFileMerge(String projectName) {
		this.projectName = projectName;
		this.setInfo(projectName);
	}
	
	@Override
	public List<String> checkConflict(String srcfn, String tfn, MData data) {
		// do prepare
		File sfile = new File(srcfn);
		File tfile = new File(tfn);
		if(!sfile.exists()) {
			return null;
		}
		if(!tfile.exists()) {
			makeTargetFile(tfn);
		}
		List<String> rl = new ArrayList<String>();
		// read data
		List<RData> trdl = null;
		try {
			srdl = XMLPaser.parseResource(srcfn, data);
			trdl = XMLPaser.parseResource(tfn);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		// do some check
		Set<String> set = new HashSet<String>();
		for(RData trd : trdl) {
			set.add(trd.value);
		}
		for(RData srd : srdl) {
			if(srd.type == RData.TYPE_IGNORE)
				continue;
			if(set.contains(srd.value)) {
				rl.add(srd.value);
				srd.type = RData.TYPE_CONFLICT;
			}
		}
		
		return rl;
	}

	
	Pattern pContent = Pattern.compile("(?ms)<resources>(?:\\s*[\r\n]+)*(.*?)(?:\\s*[\r\n]+)*</resources>");
	@Override
	public String doMerge(String srcfn, String tfn, MData data) {
		String message = CanMerge.SUCCESS, source = null, target = null;
		try {
			source = MyUtil.dealWithSource(new File(srcfn), srdl);
			target = MyUtil.getFileContent(new File(tfn));
		} catch (Exception e) {
			return e.getMessage();
		}
		
		Matcher m = pContent.matcher(source);
		String content = "";
		if(m.find()) {
			content = m.group(1);
		} else {
			return "the xml is not correct, it should contain tag <resources>";
		}
		content = beginComment + ln + content + ln + endComment + ln + "</resources>";
		content = target.replaceAll("</resources>", content);
		MyUtil.writeStringToFile(tfn, content);
		return message;
	}
	
	
	private void makeTargetFile(String tfn) {
		String sfn = DefaultXMLFileMerge.class.getResource("resources.xml").getPath();
		MyUtil.resolvePath(tfn, true);
		try {
			MyUtil.copyFile(sfn, tfn);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void setInfo(String info) {
		this.beginComment = String.format("    <!-- %s begins -->", info);
		this.endComment = String.format("    <!-- %s ends -->", info);
	}
	
	

	class Regin {
		public int start;
		public int end;
		public Regin(int start, int end) {
			this.start = start;
			this.end = end;
		}
		public void offset(int offset) {
			this.start += offset;
			this.end += offset;
		}
	}
	public static final String comment_begin = "<!-- ";
	public static final String comment_end = " -->";
	public static final int comment_num = comment_begin.length() + comment_end.length();
	private String dealWithIngoreList(String content, List<String> ignoreList) {
		List<Regin> rl = new ArrayList<Regin>();
		Set<String> set = new HashSet<String>();
		for(String c : ignoreList) {
			set.add(c);
		}
		Matcher m = filePattern.matcher(content);
		while(m.find()) {
			if(set.contains(m.group(1))) {
				rl.add(new Regin(m.start(), m.end()));
			}
		}
		int offset = 0;
		for(Regin r : rl) {
			r.offset(offset);
			String begin = content.substring(0, r.start);
			String middle = content.substring(r.start, r.end);
			String end = content.substring(r.end);
			content = String.format("%s%s%s%s%s", begin, comment_begin, middle, comment_end, end);
			offset += comment_num;
		}
		return content;
	}

}
